#include "socket.hpp"
#include <poll.h>
#include <unistd.h>
#define BUFFER_SIZE 1024

const int MAX_FD_SIZE = 64;

class poll_server {
public:
    poll_server() {
        // 初始化，方便后续找位置添加fd
        for(int i = 0; i < MAX_FD_SIZE; ++i) {
            _fd_arr[i].fd = -1;
            _fd_arr[i].events = 0;
            _fd_arr[i].revents = 0;
        }
    }

    ~poll_server() {
        _listen_sock.close();
    }

    void init() {
        _listen_sock.socket();
        _listen_sock.bind();
        _listen_sock.listen();
        lg(INFO, "server initialized");
    }

    bool add_to_fd_array(int fd) {
        for(int i = 0; i < MAX_FD_SIZE; ++i) {
            if(_fd_arr[i].fd == -1) {
                lg(INFO, "add to fd_arr, idx = %d fd = %d", i, fd);
                _fd_arr[i].fd = fd;
                _fd_arr[i].events = POLLIN;
                return true;
            }
        }
        return false;
    }
    
    void accepter() {
        struct sockaddr_in client;
        int newfd = _listen_sock.accept(&client);
        if(newfd < 0) {
            return;
        }

        if(!add_to_fd_array(newfd)) {
            lg(ERROR, "add_to_fd_array error");
            close(newfd);
            return;
            // 也可以扩容
        }    

        char ip_buff[32];
        if(inet_ntop(client.sin_family, &client.sin_addr.s_addr, ip_buff, sizeof(ip_buff)) == nullptr) {
            lg(ERROR, "inet_ntop error");
        }
        else {
            lg(INFO, "client_ip = %s, client_port = %d", ip_buff, ntohs(client.sin_port));
        }
    }

    void recever(int idx) {
        char in_buff[BUFFER_SIZE];
        int fd = _fd_arr[idx].fd;
        ssize_t n = read(fd, in_buff, sizeof(in_buff) - 1); // bug，得保证读取完整
        if(n > 0) {
            in_buff[n] = '\0';
            cout << "get a message# " << in_buff;
        }
        else {
            if(n == 0) {
                lg(INFO, "client closed");
            }
            else {
                lg(ERROR, "read error");
            }
            _fd_arr[idx].fd = -1;
            close(fd);
        }
    }
    
    // 事件派发器
    void dispatcher() {
        for(int i = 0; i < MAX_FD_SIZE; ++i) {
            int fd = _fd_arr[i].fd;
            if(fd == -1) {
                continue;
            }
            // 先判断是什么事件就绪
            // POLLIN读事件就绪
            if(_fd_arr[i].revents & POLLIN) {
                // 新连接到来
                if(fd == _listen_sock.get_sockfd()) {
                    accepter();
                }
                else {
                    // 其它套接字读事件就绪
                    recever(i);
                } 
                
            }
            else {
                // 其它事件就绪
            }
        }
    }

    void print_fd() {
        cout << "online fd list: ";
        for(int i = 0; i < MAX_FD_SIZE; ++i) {
            if(_fd_arr[i].fd != -1) {
                cout << _fd_arr[i].fd << " ";
            }
        }
        cout << endl;
    }

    void start() {
        // 将监听套接字放入数组中
        _fd_arr[0].fd = _listen_sock.get_sockfd();
        _fd_arr[0].events = POLLIN;
        int timeout = -1;
        while(true) {
            print_fd();
            int n = poll(_fd_arr, MAX_FD_SIZE, timeout);
            if(n > 0) {
                // 有事件就绪
                cout << "something happened, n = " << n << endl;
                dispatcher();
            }
            else if(n == 0) {
                // 无事件就绪
                lg(INFO, "time out...");
            }
            else {
                lg(ERROR, "poll error");
                break;
            }
        }
    }
private:
    Socket _listen_sock;
    struct pollfd _fd_arr[MAX_FD_SIZE];
};